package com.zzyy.study.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyy.study.common.BusinessExceptionUtils;
import com.zzyy.study.config.RabbitMQConfiguration;
import com.zzyy.study.dto.TransferMsg;
import com.zzyy.study.mapper.AccountMapper;
import com.zzyy.study.mq.sender.IMsgSender;
import com.zzyy.study.po.AccountPO;
import com.zzyy.study.service.IAccountService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;


@Slf4j
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, AccountPO> implements IAccountService {
    @Resource
    private AccountMapper accountMapper;

    //1 先注入 IMsgSender
    @Resource
    private IMsgSender msgSender;

    //2 再调用msgSender.send各个方法投递消息
    /*
      2.1//投递普通消息
        this.msgSender.send(消息);
      2.2//投递延迟消息
        this.msgSender.send(延迟时间, 延迟时间单位, 消息);
      2.3//投递消息到MQ
      投递消息的方法在事务中，那么投递的消息就是事务消息，如下案例
        @Override
        @Transactional(rollbackFor = Exception.class)
        public String createOrder(CreateOrderRequest req) {
            this.msgSender.sendWithBody(RabbitMQ交换机, RabbitMQ路由词, orderPO);
        }
    * */



    /**
     *
     * @param fromAccountId 付款人账户id
     * @param toAccountId   收款人账号id
     * @param transferPrice 转账金额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(String fromAccountId, String toAccountId, BigDecimal transferPrice)
    {
        //1、支付方打钱，账户余额减少
        this.balanceSubtract(fromAccountId, transferPrice);

        //2、投递RabbMQ转账消息
        TransferMsg transferMsg = new TransferMsg(fromAccountId, toAccountId, transferPrice);

        this.msgSender.sendWithBody(RabbitMQConfiguration.Transfer.EXCHANGE,
                RabbitMQConfiguration.Transfer.ROUTING_KEY,
                transferMsg);
    }

    /**
     * 增加账户余额
     *
     * @param accountId
     * @param price
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void balanceAdd(String accountId, BigDecimal price) {
        int update = this.accountMapper.balanceAdd(accountId, price);
        if (update != 1) {
            throw BusinessExceptionUtils.businessException("更新账号余额失败!");
        }
    }

    /**
     * 减少账户余额
     *
     * @param accountId
     * @param price
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void balanceSubtract(String accountId, BigDecimal price) {
        //返回值表示影响的行数
        int update = this.accountMapper.balanceSubtract(accountId, price);
        if (update != 1) {
            throw BusinessExceptionUtils.businessException("更新账号余额失败!");
        }
    }
}


